home *** CD-ROM | disk | FTP | other *** search
- ; IO.S
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Scheme code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Standard Scheme Input/Output Routines *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: David Bartley Date: 1985 *
- ;* Revision history: *
- ;* - 10 Feb 87: READ modified for R^3 quasi/quote *
- ;* READ-STRING removed and coded in assembler *
- ;* Random I/O included from David Stevens (tc) *
- ;* - 2 Jun 87: Open-binary-input-file,open-binary-output-file *
- ;* compile, etc. removed and placed in COMP.S *
- ;* for building of compiler-less system *
- ;* LOAD is just defined in terms of FAST-LOAD *
- ;* for compilerless systems. Its real definition *
- ;* is in COMP.S. (tc) *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* - 15 Dec 92: Added PEEK-CHAR for R4RS; added READ-SW for sweb (mv) *
- ;* - 25 Dec 92: Added SPLIT-FILENAME using %ESC *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
-
- ; The following definitions are used only at compile time for readability
- ; and understanding. They will not be written out to the .so file.
- ; See pboot.s and compile.all.
-
- (compile-time-alias %read-file-flag #b00000001) ; read flag
- (compile-time-alias %write-file-flag #b00000011) ; write flag(s)
- (compile-time-alias %window-flag #b00000100) ; window port
- (compile-time-alias %open-file-flag #b00001000) ; open port
- (compile-time-alias %binary-file-flag #b00100000) ; binary file
- (compile-time-alias %string-flag #b01000000) ; string file
-
-
- (define call-with-input-file ; CALL-WITH-INPUT-FILE
- (lambda (filename proc)
- (let* ((port (open-input-file filename))
- (answer (proc port)))
- (close-input-port port)
- answer)))
-
-
- (define call-with-output-file ; CALL-WITH-OUTPUT-FILE
- (lambda (filename proc)
- (let* ((port (open-output-file filename))
- (answer (proc port)))
- (close-output-port port)
- answer)))
-
-
- (define current-column ; CURRENT-COLUMN
- (lambda args
- (+ 1 (%reify-port (car args) 1))))
-
-
- (define-integrable current-input-port ; CURRENT-INPUT-PORT
- (lambda ()
- (fluid input-port)))
-
- (define-integrable current-output-port ; CURRENT-OUTPUT-PORT
- (lambda ()
- (fluid output-port)))
-
- (define eof-object? ; EOF-OBJECT?
- (lambda (obj)
- (eqv? obj eof))) ; temporary ???
-
-
- ;;;
- ;;; Compile functions are now in PCOMP.S, ; COMPILE
- ;;; which reflects compiler-only functions
- ;;;
-
-
- (define fast-load ; FAST-LOAD
- (lambda (file)
- (letrec ((fasl
- (lambda (name)
- (let ((pgm (%%fasl name)))
- (when (not (eof-object? pgm))
- (%execute pgm)
- (fasl '() ))))))
- (if (string? file)
- (if (file-exists? file)
- (begin
- (fasl file)
- 'ok)
- (error "FAST-LOAD file does not exist" file))
- (%error-invalid-operand 'FAST-LOAD file)))))
-
- (if (unbound? load)
- (define load fast-load)) ; LOAD
-
- (define file-exists? ; FILE-EXISTS?
- (lambda (name)
- (and (string? name)
- (not (string-null? name))
- (call/cc
- (fluid-lambda (*file-exists-open*)
- (let ((port (%open-port name 'read)))
- (if (port? port)
- (begin
- (close-input-port port)
- #T)
- ;else
- #F)))))))
-
-
- (define filename-split ; FILENAME-SPLIT
- (lambda (name)
- (if (string? name)
- (read (open-input-string (%esc 6 name)))
- (error "invalid argument to FILENAME-SPLIT" name))))
-
- (define filename-merge ; FILENAME-MERGE
- (lambda (path)
- (apply string-append path)))
-
- (define flush-input ; FLUSH-INPUT
- (lambda args
- (let ((x '())
- (port (car args)))
- (if (and (positive? (bitwise-and (%reify-port port 11) %open-file-flag))
- (zero? (bitwise-and (%reify-port port 11) %read-file-flag))
- (char-ready? port))
- (do ((x (read-char port) (read-char port)) )
- ((or (eq? x #\newline)
- (eof-object? x)
- (not (char-ready? port)))))))))
-
-
-
- (define fresh-line ; FRESH-LINE
- (lambda p
- (when p (set! p (car p)))
- (when (positive? (%reify-port p 1))
- (newline p))))
-
-
- (define input-port? ; INPUT-PORT?
- (lambda (p)
- (and (port? p)
- (let ((pflags (%reify-port p 11)))
- (and (positive? (bitwise-and %open-file-flag pflags))
- (zero? (bitwise-and %read-file-flag pflags)))))))
-
- (define line-length ; LINE-LENGTH
- (lambda args
- (%reify-port (car args) 5)))
-
- (define open-input-file ; OPEN-INPUT-FILE
- (lambda (name) (%open-port name 'read)))
-
- (define open-binary-input-file ; OPEN-BINARY-INPUT-FILE
- (lambda (name)
- (let ((port (%open-port name 'read)))
- (%reify-port!
- port
- 11
- (bitwise-or %binary-file-flag (%reify-port port 11)))
- port)))
-
- (define open-output-file ; OPEN-OUTPUT-FILE
- (lambda (name) (%open-port name 'write)))
-
- (define open-binary-output-file ; OPEN-BINARY-OUTPUT-FILE
- (lambda (name)
- (let ((port (%open-port name 'write)))
- (%reify-port!
- port
- 11
- (bitwise-or %binary-file-flag (%reify-port port 11)))
- (set-line-length! 0 port)
- port)))
-
- (define open-extend-file ; OPEN-EXTEND-FILE
- (lambda (name) (%open-port name 'append)))
-
- (define close-input-port ; CLOSE-INPUT-PORT
- (lambda (port) (%close-port port)))
-
- (define close-output-port ; CLOSE-OUTPUT-PORT
- (lambda (port) (%close-port port)))
-
-
- (define (open-input-string str) ; OPEN-INPUT-STRING
- (if (string? str)
- (let ((p (%make-window '())))
- (%reify! p 0 str)
- (%reify-port! p 2 3)
- (%reify-port! p 11 (bitwise-and
- (bitwise-or %string-flag (%reify-port p 11))
- #xfd))
- p)
- (%error-invalid-operand 'OPEN-INPUT-STRING str)))
-
-
- (define output-port? ; OUTPUT-PORT?
- (lambda (p)
- (and (port? p)
- (let ((pflags (%reify-port p 11)))
- (and (positive? (bitwise-and %open-file-flag pflags))
- (positive? (bitwise-and %write-file-flag pflags)))))))
-
- (define (peek-char . p)
- (let* ((char (apply read-char p)))
- (if (not (eof-object? char))
- (apply unread-char p))
- char))
-
- (define read ; READ
- (letrec
- ((rd-object
- (lambda (port qq?)
- (let ((item (read-atom port)))
- (cond ((eof-object? item) item)
- ((atom? item) item)
- (else
- (let ((item (car item)))
- (case item
- (|#(| (rd-vector-tail port qq?))
- ( |(| (rd-list-tail port qq?))
- ( |)| (error "Unexpected `)' encountered before `('"))
- ( |.| (dot-warning) (rd-object port qq?))
- ( |`| (rd-mac port #T item #F))
- ( |'| (rd-mac port qq? item #F))
- ((|[| |]| |{| |}|)
- item)
- (else (rd-mac port qq? item #T)))))))))
- (rd-mac
- (lambda (port qq? item qq-op?)
- (if (and (not qq?) qq-op?)
- (error "Invalid outside of QUASIQUOTE expression:" item)
- (let ((obj (rd-object port qq?)))
- (if (eof-object? obj)
- (eof-warning)
- (list (cdr (assq item qq-ops)) obj))))))
- (rd-vector-tail
- (lambda (port qq?)
- (list->vector (rd-tail port qq? #F '()))))
- (rd-list-tail
- (lambda (port qq?)
- (rd-tail port qq? #T '())))
- (rd-tail
- (lambda (port qq? dot-ok? result)
- (let ((item (read-atom port)))
- (cond ((eof-object? item)
- (eof-warning)
- (%reverse! result))
- ((atom? item)
- (if (eq? item 'quasiquote)
- (rd-tail port #T dot-ok? (cons item result))
- ;else
- (rd-tail port qq? dot-ok? (cons item result))))
- (else
- (let ((item (car item)))
- (case item
- ( |)| (%reverse! result))
- ( |.| (if (and dot-ok? (not (null? result)))
- (rd-dotted-tail port qq? result)
- (begin
- (dot-warning)
- (rd-tail port qq? dot-ok? result))))
- (else
- (let ((obj (case item
- (|#(| (rd-vector-tail port qq?))
- ( |(| (rd-list-tail port qq?))
- ( |`| (rd-mac port #T item #F))
- ( |'| (rd-mac port qq? item #F))
- ((|[| |]| |{| |}|)
- item)
- (else (rd-mac port qq? item #T)))))
- (rd-tail port qq? dot-ok? (cons obj result)))))))))))
- (rd-dotted-tail
- (lambda (port qq? result)
- (let ((tail (rd-tail port qq? #F '())))
- (append! (%reverse! result)
- (cond ((and (pair? tail)
- (null? (cdr tail)))
- (car tail))
- (else
- (dot-warning)
- tail))))))
- (dot-warning
- (lambda ()
- (newline)
- (display "WARNING -- Invalid use of `.' encountered during READ")))
- (eof-warning
- (lambda ()
- (newline)
- (display "WARNING -- EOF encountered during READ")
- eof))
- (qq-ops
- '((|'| . QUOTE)
- (|`| . QUASIQUOTE)
- (|,| . UNQUOTE)
- (|,@| . UNQUOTE-SPLICING)
- (|,.| . UNQUOTE-SPLICING!))))
- (lambda args
- (let ((port (car args)))
- (rd-object port #F)))))
-
- ;
- ; READ-LINE re-coded in assembly language on 2-10-86 by TC
- ;
- ;(define read-line ; READ-LINE
- ; (lambda args
- ; (define (readln-rec port n char char-list)
- ; (cond ((eof-object? char)
- ; (if (null? char-list)
- ; char
- ; (fill-string (trim char-list))))
- ; ((eqv? char #\return)
- ; (if (null? char-list)
- ; ""
- ; (fill-string (trim char-list))))
- ; ((eqv? char #\newline)
- ; (readln-rec port n (read-char port) char-list))
- ; (else
- ; (readln-rec port (+ n 1) (read-char port)
- ; (cons char char-list)))))
- ; (define (trim char-list)
- ; (cond ((null? char-list)
- ; '())
- ; ((eqv? (car char-list) #\space)
- ; (trim (cdr char-list)))
- ; (else
- ; char-list)))
- ; (define (fill-string char-list)
- ; (let ((size (length char-list)))
- ; (fill-rec char-list (- size 1) (make-string size '()))))
- ; (define (fill-rec char-list i string)
- ; (if (null? char-list)
- ; string
- ; (begin
- ; (string-set! string i (car char-list))
- ; (fill-rec (cdr char-list) (- i 1) string))))
- ; (let ((port (and args (car args))))
- ; (readln-rec port 0 (read-char port) '()))))
- ;
-
- ; Extracted of reader.sw, by John D. Ramsdell, 90/07/12 ; READ-SW
- ; Converts SchemeWEB representations of Scheme objects
- ; into the objects themselves much as READ does.
-
- (define (read-sw . rest) ; Returns what \verb;read; returns.
- (let ((port (if (pair? rest) ; \verb;read-sw; arguments are
- (car rest) ; the same as \verb;read;'s.
- (current-input-port))))
- (letrec
- ((text-mode-and-saw-newline ; Lines of a Scheme\WEB{} file
- (lambda () ; beginning with ``{\tt(}'',
- (let ((ch (peek-char port))) ; start a code section.
- (cond ((eof-object? ch) ch)
- ((char=? ch #\() ; If code section, then use
- (got-code (read port))) ; \verb;read; to get code,
- (else ; else skip this line as it
- (text-mode-within-a-line)))))) ; is a comment.
- (text-mode-within-a-line
- (lambda () ; Ignore comments.
- (let ((ch (read-char port)))
- (cond ((eof-object? ch) ch)
- ((char=? ch #\newline)
- (text-mode-and-saw-newline))
- (else (text-mode-within-a-line))))))
- (got-code
- (lambda (code) ; Ignore the remainder of the
- (let ((ch (read-char port))) ; last code line and return
- (cond ((eof-object? ch) code) ; the results of \verb;read;.
- ((char=? ch #\newline)
- code)
- (else (got-code code)))))))
- (text-mode-and-saw-newline) ; Start by looking
- ))) ; for a code line.
-
-
- (define set-line-length! ; SET-LINE-LENGTH!
- (lambda (value . rest)
- (%reify-port! (car rest) 5 value)
- '()))
-
-
- (define transcript-on)
- (define transcript-off)
-
- (let ((port '()))
- (set! transcript-on ; TRANSCRIPT-ON
- (lambda (file)
- (when (not (null? port))
- (transcript-off))
- (cond ((string? file)
- (set! port (open-extend-file file))
- (if (port? port)
- (begin
- (%transcript port)
- 'ok )
- (begin
- (set! port '())
- (error "Unable to open transcript file" file))))
- ((window? file)
- (set! port file)
- (%transcript file)
- 'ok)
- (else
- (error "Invalid argument to transcript-on" file)))))
-
- (set! transcript-off ; TRANSCRIPT-OFF
- (lambda ()
- (when (not (null? port))
- (%transcript '())
- (close-output-port port)
- (set! port '()))
- 'ok)))
-
- ;;; WITH-INPUT-FROM-FILE and WITH-OUTPUT-TO-FILE need to be rewritten
- ;;; to use DYNAMIC-WIND, or its equivalent.
-
- (define with-input-from-file ; WITH-INPUT-FROM-FILE
- (lambda (filename thunk)
- (let ((port (open-input-file filename)))
- (if (port? port)
- (let ((ans (fluid-let ((input-port port)) (thunk))))
- (close-input-port port)
- ans)
- port))))
-
- (define with-output-to-file ; WITH-OUTPUT-TO-FILE
- (lambda (filename thunk)
- (let ((port (open-output-file filename)))
- (if (port? port)
- (let ((ans (fluid-let ((output-port port)) (thunk))))
- (close-output-port port)
- ans)
- port))))
-
- (define window? ; WINDOW?
- (lambda (obj)
- (and (port? obj)
- (positive? (bitwise-and (%reify-port obj 11) %window-flag)))))
-
- (define input-string?
- (lambda (obj)
- (and (window? obj)
- (not (output-port? obj)))))
-
- (define writeln ; WRITELN
- (lambda args
- (do ((args args (cdr args)))
- ((null? args)
- (newline))
- (display (car args)))))
-
- ;****************************************************************************
- ;* SET-FILE-POSITION will move the file pointer to a new position *
- ;* and update a pointer in the buffer to point to a new location. *
- ;* The offset variable can be: *
- ;* 0 for positioning from the start of the file *
- ;* 1 for positioning relative to the current position *
- ;* 2 for positioning from the end of the file *
- ;****************************************************************************
-
- (define set-file-position! ; SET-FILE-POSITION!
- (lambda (port amount whence)
- (let ((port-flags (%reify-port port 11)))
- (cond ((input-string? port)
- (let ((%set-pos
- (lambda (pos)
- (if (< pos 0)
- (%error-invalid-operand 'SET-FILE-POSITION! pos))
- (%reify-port! port 9 0) ; begin of buffer
- (%reify-port! port 10 0) ; empty buffer
- (%reify-port! port 12 (+ pos 3))))); where to start reading
- (case whence
- ((0 SET) (%set-pos amount))
- ((1 CUR) (%set-pos (+ (get-file-position port) amount)))
- ((2 END) (%set-pos (- (string-length (%reify-port port 13)) amount)))
- (else (%error-invalid-operand 'SET-FILE-POSITION! whence)))))
-
- ((and (port? port) (not (window? port)))
- (let* ((file-size (+ (* (%reify-port port 4) #x10000)
- (%reify-port port 6)))
- (%set-pos
- (lambda (pos)
- (if (= (bitwise-and port-flags %write-file-flag) 0)
- (set! pos (min pos file-size)))
- (if (< pos 0)
- (%error-invalid-operand 'SET-FILE-POSITION! pos))
- (let ((new-pos (remainder pos #x100))
- (old-chunk (max 0 (-1+ (%reify-port port 12))))
- (new-chunk (quotient pos #x100)))
- (if (and (= new-chunk old-chunk)
- (= (bitwise-and port-flags %write-file-flag) 0))
- (%reify-port! port 9 new-pos)
- (%sfpos port new-chunk new-pos))))))
- (case whence
- ((0 SET) (%set-pos amount))
- ((1 CUR) (%set-pos (+ (get-file-position port) amount)))
- ((2 END) (%set-pos (- file-size amount)))
- (else (%error-invalid-operand 'SET-FILE-POSITION! whence)))))
- (else (%error-invalid-operand 'SET-FILE-POSITION! port))))))
-
- ;******************************************************************
- ;* get-file-position will return the current file position in the *
- ;* number of bytes from the beginning of the file. *
- ;******************************************************************
-
- (define get-file-position ; GET-FILE-POSITION
- (lambda (port)
- (cond ((and (port? port) (not (window? port)))
- (+ (* 256 (max 0 (-1+ (%reify-port port 12)))) ; chunk#
- (%reify-port port 9))) ; offset
- ((input-string? port)
- (+ (- (%reify-port port 12) 3 (%reify-port port 10))
- (%reify-port port 9)))
- (else (%error-invalid-operand 'GET-FILE-POSITION! port)))))
-